import * as vscode from "vscode";
import { join, dirname, normalize } from "path";
import { existsSync, readFileSync } from "fs";

export class RouterlHoverProvider implements vscode.HoverProvider {
  provideHover(document: vscode.TextDocument, position: vscode.Position) {
    const fileName = document.fileName;
    const workDir = dirname(fileName);
    const word = document.getText(document.getWordRangeAtPosition(position));
    const line: any = document.lineAt(position);

    let workspacePath = "";
    if (vscode.workspace.workspaceFolders?.length) {
      workspacePath = vscode.workspace.workspaceFolders[0].uri.fsPath;
      workspacePath = normalize(workspacePath);
    }
    const cwd = workspacePath;

    let newPath: string = "";
    let uri: string = "";
    let showName = "";
    const vscodeNode: any[] = [];
    // 获取用户设置
    const configurate = vscode.workspace
      .getConfiguration()
      .get("vh-tips-tool.type");

    if (configurate === "vh-admin") {
      let ok: boolean = false;

      if (line.text.includes("component:")) {
        ok = true;
      } else if (line.text.includes("path:")) {
        ok = true;
      } else if (line.text.includes("history.push")) {
        ok = true;
      }

      if (!ok || !word) {
        return;
      }

      if (line.text.includes("component:")) {
        const wordRegex = new RegExp(`'@.*'`, "g");
        const wordMatch: any = line.text.match(wordRegex);
        if (!wordMatch[0]) {
          return;
        }
        newPath = wordMatch[0].replace(/'/g, "").replace(/@/g, "").trim();
        showName = newPath;
      } else {
        const wordRegex = new RegExp(`/.*'`, "g");
        const wordMatch: any = line.text.match(wordRegex);
        if (!wordMatch[0]) {
          return;
        }
        newPath = wordMatch[0].replace("'", "").trim();
        showName = newPath;
        try {
          let ProviderPath: string = join(
            cwd,
            "src",
            ".umi",
            "core",
            "route.tsx"
          );
          const ProviderFile = readFileSync(ProviderPath).toString();

          const numRegex = new RegExp(`const.*as`, "g");
          const match: any = ProviderFile.match(numRegex);
          if (!match[0]) {
            return;
          }
          const pstr: string = match[0];
          const vstr: string = pstr
            .replace("=", "")
            .replace("routes", "")
            .replace("const", "")
            .replace("as", "")
            .replace(/\s/g, "")
            .trim();
          const route = JSON.parse(vstr);

          const n = ProviderFile.replace(/[\t*|\s*]/g, "");
          const rRegex = new RegExp(`routeComponents:.*}`, "g");
          const rmatch: any = n.match(rRegex);

          if (!rmatch[0]) {
            return;
          }
          const rstr: string = rmatch[0];
          const rArr: any[] = rstr.split(",");
          if (rArr.length === 0) {
            return;
          }
          const components: any[] = [];
          rArr.forEach((i) => {
            const nmatch: any = i.match(/'\d+'/g);
            if (nmatch && nmatch[0]) {
              const num = nmatch[0].replace(/'/g, "").trim();
              const pmatch: any = i.match(/'@.*'/g);
              if (pmatch && pmatch[0]) {
                const path = pmatch[0]
                  .replace(/@/g, "")
                  .replace(/'/g, "")
                  .trim();
                components.push({
                  key: num,
                  path: path,
                });
              }
            }
          });

          let has: any;
          Object.keys(route).forEach((key) => {
            if (route[key] && route[key].path && route[key].path == newPath) {
              has = route[key];
            }
          });

          if (!has) {
            return;
          }

          const newPathHas = components.find((i: any) => i.key == has.id);

          if (!newPathHas) {
            return;
          }

          newPath = newPathHas.path;
        } catch (error) {
          console.log("===================");
          console.log(error);
          console.log("===================");
        }
      }

      uri = join(cwd, "src", newPath);

      let definitionFile = "";

      if (uri.indexOf(".") > -1) {
        definitionFile = uri;
      } else {
        if (existsSync(`${uri}.ts`)) {
          definitionFile = `${uri}.ts`;
        } else if (existsSync(`${uri}.tsx`)) {
          definitionFile = `${uri}.tsx`;
        } else if (existsSync(`${uri}.js`)) {
          definitionFile = `${uri}.js`;
        } else if (existsSync(`${uri}.jsx`)) {
          definitionFile = `${uri}.jsx`;
        }
      }
      if (existsSync(definitionFile)) {
        vscodeNode.push({
          name: showName,
          path: definitionFile,
        });
      }
    } else {
      let ok: boolean = false;

      const lineMatch = line.text.match(/'\/?pages\/+.*'/g);

      if (lineMatch && lineMatch[0]) {
        ok = true;
      }

      if (!ok) {
        return;
      }

      lineMatch.forEach((p: string) => {
        newPath = p.replace(/'/g, "").replace(/@/g, "").trim();
        if (newPath.substring(0, 1) !== "/") {
          newPath = "/" + newPath;
        }
        showName = newPath;

        uri = join(cwd, "src", newPath);

        let definitionFile = "";

        if (uri.indexOf(".") > -1) {
          definitionFile = uri;
        } else {
          if (existsSync(`${uri}.ts`)) {
            definitionFile = `${uri}.ts`;
          } else if (existsSync(`${uri}.tsx`)) {
            definitionFile = `${uri}.tsx`;
          } else if (existsSync(`${uri}.js`)) {
            definitionFile = `${uri}.js`;
          } else if (existsSync(`${uri}.jsx`)) {
            definitionFile = `${uri}.jsx`;
          }
        }

        if (existsSync(definitionFile)) {
          vscodeNode.push({
            name: showName,
            path: definitionFile,
          });
        }
      });
    }

    try {
      if (vscodeNode.length > 0) {
        return new vscode.Hover(`
${vscodeNode.map(
  (v) =>
    `#### 路由：${v.name}
[${v.path}](${vscode.Uri.file(v.path)})`
)}
`);
      }
    } catch (error) {
      console.log("===================");
      console.log(error);
      console.log("===================");
    }
  }
}
